/**
 * @Description 发布订阅模式
 * @param subscribe 订阅者
 * @param publish 发布者
 * @param unSubscribe: 移除订阅者
 * @date 2020-11-18
 * @returns {any}
 */
class PubSub {
    constructor() {
        this.subs = []
    }

    subscribe (key, fn) {
        if (!this.subs[key]) {
            this.subs[key] = []
        }
        this.subs[key].push(fn)
    }

    publish (key, ...args) {
        if (!this.subs[key] || !this.subs[key].length) {
            console.error('no length');
            return
        }
        this.subs[key].forEach(element => {
            element.apply(null, args)
        });
    }

    unSubscribe (key) {
        delete this.subs[key]
    }
}

let pubsub = new PubSub();
pubsub.subscribe('name', name => {
    console.log(`your name is ${name}`);
})

pubsub.subscribe('age', age => {
    console.log(`your age is ${age}`);
})
pubsub.subscribe('job', age => {
    console.log(`your job is ${age}`);
})

pubsub.publish('name', 'jackvaonima');

pubsub.publish('age', '18');

pubsub.publish('job', 'design');

pubsub.unSubscribe('job')


/**
 * @Description 另一种实现
 * @date 2020-11-18
 * @returns {any}
 */
class PublishSubscribe {
    constructor() {
        this.handles = {}
    }

    on (event, fn) {
        // 判断对象是否有这个事件的属性key
        if (!this.handles.hasOwnProperty(event)) {
            this.handles[event] = []
        }

        if (typeof fn === 'function') {
            this.handles[event].push(fn)
        } else {
            console.error(`${fn} is not a function`);
        }
        return this
    }

    emit (event, ...arg) {
        if (!this.handles.hasOwnProperty(event)) {
            console.error(`${event} event not registered`);
        } else {
            this.handles[event].forEach(element => {
                // 改变了订阅的事件中的值，观察者模式中最核心的部分
                element.apply(null, arg)
            });
        }
        return this
    }

    off (event, fn) {
        if (!this.handles.hasOwnProperty(event)) {
            console.error(`${event} event not registered`);
        }
        if (typeof fn === 'function') {
            this.handles[event].forEach((element, index, arr) => {
                // 强等必须转字符串，引用类型不可
                if (element.toString() === fn.toString()) {
                    arr.splice(index, 1)
                }
            });
        } else {
            console.error(`${fn} is not a function`);
        }
        return this
    }
}

let callback = function () {
    console.log('you are so nice');
}

let observer = new PublishSubscribe();

observer.on('complued', (...args) => {
    console.log(args.join(' '));
})


observer.emit('complued', 'what', 'a', 'fucking day')

observer.off('complued', callback);

observer.emit('complued', 'fucking', 'again')